﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

using Elifart.Editor.GeneralControls;
using Elifart.Library;

namespace Elifart.Editor.CategoryTabs.AssociationControls
{
    public partial class FootballAssociationControl : UserControl
    {
        #region Constructor

        public FootballAssociationControl()
        {
            InitializeComponent();
        }

        #endregion

        #region Private Fields

        private bool _loadingAssociation;

        private IEnumerable<Association> _searchResultsEnumerable;
        private IEnumerator<Association> _searchResultsEnumerator;

        #endregion

        #region Private Methods

        private void BuildAssociationsTreeView(TreeNodeCollection treeNodeCollection, AssociationCollection associations)
        {
            this.tvw_associations.TreeViewNodeSorter = new AssociationTreeViewSorter();

            if (associations == null)
                return;
            foreach (Association association in associations)
            {
                AssociationTreeNode associationTreeNode = new AssociationTreeNode(association, this.iml_associationFlags);
                treeNodeCollection.Add(associationTreeNode);
                this.BuildAssociationsTreeView(associationTreeNode.Nodes, association.Members);
            }
        }

        private void LoadAssociation()
        {
            this._loadingAssociation = true;

            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            Association association = null;
            if (associationTreeNode != null)
                association = associationTreeNode.Association;

            this.pnl_associationInfo.Enabled = association != null;
            this.btn_newChildAssociation.Enabled = association != null;
            this.btn_removeAssociation.Enabled = association != null;

            if (association == null)
                this.ResetAssociation();
            else
            {
                this.LoadAssociationInfo(association);
                this.LoadAssociationRegisteredMembers(associationTreeNode);
                this.LoadAssociationFlagPreview(association);
            }
            
            this._loadingAssociation = false;
        }

        private void LoadAssociationInfo(Association association)
        {
            this.txt_associationName.Text = association.Name;
            this.txt_associationAbbreviation.Text = association.Abbreviation;
            //this.dtp_associationfoundingDate.Text = association.FoundingDate.ToShortDateString();

            if (string.IsNullOrEmpty(association.FlagName))
                this.btn_associationFlag.Text = "...";
            else
                this.btn_associationFlag.Text = association.FlagName;

            Association associationAffiliation = AssociationManager.GetManager().Associations[association.AffiliationGUID];
            if (associationAffiliation != null)
                this.txt_associationAffiliation.Text = associationAffiliation.Name;
            else
                this.txt_associationAffiliation.Text = string.Empty;
        }

        private void LoadAssociationFlagPreview(Association association)
        {
            this.pbx_associationFlagPreview.Image = AssociationManager.GetManager().GetAssociationFlag(association.FlagName);
            if (this.pbx_associationFlagPreview.Image == null)
                this.pbx_associationFlagPreview.Image = Properties.Resources.flag;
        }

        private void LoadAssociationRegisteredMembers(AssociationTreeNode associationTreeNode)
        {
            List<AssociationTreeNode> associationTreeNodes = new List<AssociationTreeNode>();
            foreach (TreeNode treeNode in associationTreeNode.Nodes)
                associationTreeNodes.Add(treeNode as AssociationTreeNode);

            this.dgv_associationRegisteredMembers.DataSource = associationTreeNodes;
        }

        private void NewAssociation(bool iSisterAssociation)
        {
            Association association = new Association();
            association.Name = "Associação de Futebol";
            association.Abbreviation = "AF";
            //association.FoundingDate = DateTime.Now;
            association.FlagName = string.Empty;

            TreeNodeCollection treeNodeCollection = this.tvw_associations.Nodes;

            if ((this.tvw_associations.SelectedNode != null))
            {
                if (!iSisterAssociation)
                {
                    AssociationTreeNode parentAssociationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
                    treeNodeCollection = this.tvw_associations.SelectedNode.Nodes;
                    association.AffiliationGUID = parentAssociationTreeNode.Association.GUID;
                }
                else
                {
                    AssociationTreeNode parentAssociationTreeNode = this.tvw_associations.SelectedNode.Parent as AssociationTreeNode;
                    if (parentAssociationTreeNode != null)
                    {
                        treeNodeCollection = parentAssociationTreeNode.Nodes;
                        association.AffiliationGUID = parentAssociationTreeNode.Association.GUID;
                    }
                    else
                    {
                        treeNodeCollection = this.tvw_associations.Nodes;
                        association.AffiliationGUID = string.Empty;
                    }
                }
            }

            AssociationTreeNode associationTreeNode = new AssociationTreeNode(association, this.iml_associationFlags);

            string key = string.Empty;
            if (associationTreeNode.FlagImage != null)
                key = associationTreeNode.FlagImage.GetHashCode().ToString();

            if (associationTreeNode.FlagImage != null)
                this.iml_associationFlags.Images.Add(key, associationTreeNode.FlagImage);

            associationTreeNode.ImageKey = key;
            associationTreeNode.SelectedImageKey = key;
            associationTreeNode.StateImageKey = key;

            if (this.tvw_associations.SelectedNode != null)
                this.tvw_associations.SelectedNode.Expand();

            this.tvw_associations.SelectedNode = associationTreeNode;

            AssociationManager.GetManager().Associations.Add(association);
            treeNodeCollection.Add(associationTreeNode);
        }

        private void RemoveAssociation()
        {
            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode == null) return;

            Association association = associationTreeNode.Association;
            if (AssociationManager.GetManager().Associations.Remove(association))
                this.tvw_associations.SelectedNode.Remove();
        }

        private void ResetAssociation()
        {
            this.txt_associationName.Text = string.Empty;
            this.txt_associationAbbreviation.Text = string.Empty;
            this.dtp_associationfoundingDate.Text = string.Empty;
            this.btn_associationFlag.Text = "...";
            this.txt_associationAffiliation.Text = string.Empty;

            this.pbx_associationFlagPreview.Image = Properties.Resources.flag;

            this.dgv_associationRegisteredMembers.DataSource = null;
            this.dgv_associationRegisteredMembers.Rows.Clear();
        }

        private void SearchAssociations()
        {
            var lastsearchResults = from item in AssociationManager.GetManager().Associations
                                    where (item as Association).Abbreviation.StartsWith(this.txt_associationsSearch.Text, StringComparison.InvariantCultureIgnoreCase)
                                    select item as Association;

            this._searchResultsEnumerable = lastsearchResults;
            this._searchResultsEnumerator = this._searchResultsEnumerable.GetEnumerator();
            this.SearchNextAssociation();
        }

        private void SearchNextAssociation()
        {
            if (this._searchResultsEnumerator == null) return;
            if (!this._searchResultsEnumerator.MoveNext())
            {
                this._searchResultsEnumerator = this._searchResultsEnumerable.GetEnumerator();
                this._searchResultsEnumerator.MoveNext();
            }

            if (this._searchResultsEnumerator.Current != null)
                this.tvw_associations.SelectedNode = this.tvw_associations.Nodes[this._searchResultsEnumerator.Current.GUID];
        }

        #endregion

        #region Signed Events Methods

        private void AssociationControl_Load(object sender, System.EventArgs e)
        {
            this.dgv_associationRegisteredMembers.AutoGenerateColumns = false;
            this.BuildAssociationsTreeView(this.tvw_associations.Nodes, AssociationManager.GetManager().Associations);
            if (this.tvw_associations.SelectedNode != null)
            {
                this.tvw_associations.SelectedNode = this.tvw_associations.Nodes[0];
                this.tvw_associations.SelectedNode.Expand();
            }
            this.LoadAssociation();
        }

        private void Association_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            this.tvw_associations.Refresh();
            this.dgv_associationRegisteredMembers.Refresh();
            this.LoadAssociation();
        }

        private void btn_next_Click(object sender, EventArgs e)
        {
            this.SearchNextAssociation();
        }

        private void btn_newChildAssociation_Click(object sender, System.EventArgs e)
        {
            this.NewAssociation(false);
            this.LoadAssociation();
        }

        private void btn_newSisterAssociation_Click(object sender, EventArgs e)
        {
            this.NewAssociation(true);
            this.LoadAssociation();
        }

        private void btn_removeAssociation_Click(object sender, System.EventArgs e)
        {
            this.RemoveAssociation();
            this.LoadAssociation();
        }

        private void btn_associationFlag_Click(object sender, System.EventArgs e)
        {
            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode.Association == null) return;

            FileChooser chooser = new FileChooser(associationTreeNode.Association.FlagName, AssociationManager.ASSOCIATIONS_FLAGS_DIRECTORY);
            chooser.StartPosition = FormStartPosition.CenterParent;            
            
            DialogResult result = chooser.ShowDialog(this);
            if (result != DialogResult.OK) return;
                
            this.btn_associationFlag.Text = chooser.SelectedImage;
            associationTreeNode.Association.FlagName = chooser.SelectedImage;

            this.tvw_associations.SelectedNode = null;
            this.tvw_associations.SelectedNode = associationTreeNode;
        }

        private void dgv_associationRegisteredMembers_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridViewRow selectedRow = this.dgv_associationRegisteredMembers.SelectedRows[0];
            AssociationTreeNode associationTreeNode = selectedRow.DataBoundItem as AssociationTreeNode;
            this.tvw_associations.SelectedNode = associationTreeNode;
        }

        private void dtp_foundingDate_ValueChanged(object sender, EventArgs e)
        {
            if (this._loadingAssociation) return;
            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode == null) return;
            if (associationTreeNode.Association == null) return;
            //this._associations associationTreeNode.Association.FoundingDate = this.dtp_associationfoundingDate.Value;
        }

        private void tvw_associations_AfterSelect(object sender, TreeViewEventArgs e)
        {
            this.tvw_associations.SelectedNode.BackColor = SystemColors.MenuHighlight;
            this.tvw_associations.SelectedNode.ForeColor = SystemColors.Window;

            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode != null)
                if (associationTreeNode.Association != null)
                {
                    associationTreeNode.Association.Notifier.PropertyChanged += Association_PropertyChanged;
                    if (associationTreeNode.FlagImage != null)
                    {
                        associationTreeNode.ImageKey = associationTreeNode.FlagImage.GetHashCode().ToString();
                        associationTreeNode.SelectedImageKey = associationTreeNode.FlagImage.GetHashCode().ToString();
                    }
                    else
                    {
                        associationTreeNode.ImageKey = "transparent.jpg";
                        associationTreeNode.SelectedImageKey = "transparent.jpg";
                    }
                }

            this.LoadAssociation();
        }

        private void tvw_associations_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            if (this.tvw_associations.SelectedNode == null) return;

            this.tvw_associations.SelectedNode.BackColor = this.tvw_associations.BackColor;
            this.tvw_associations.SelectedNode.ForeColor = this.tvw_associations.ForeColor;

            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode.Association == null) return;
            associationTreeNode.Association.Notifier.PropertyChanged -= Association_PropertyChanged;
        }

        private void txt_associationAbbreviation_TextChanged(object sender, EventArgs e)
        {
            if (this._loadingAssociation) return;
            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode == null) return;
            if (associationTreeNode.Association == null) return;
            associationTreeNode.Association.Abbreviation = this.txt_associationAbbreviation.Text;
        }

        private void txt_associationName_TextChanged(object sender, EventArgs e)
        {
            if (this._loadingAssociation) return;
            AssociationTreeNode associationTreeNode = this.tvw_associations.SelectedNode as AssociationTreeNode;
            if (associationTreeNode == null) return;
            if (associationTreeNode.Association == null) return;
            associationTreeNode.Association.Name = this.txt_associationName.Text;
        }

        private void txt_associationsSearch_TextChanged(object sender, EventArgs e)
        {
            this.SearchAssociations();
        }

        #endregion
    }
}
